package com.saceem.imagenes;

import java.awt.image.renderable.ParameterBlock;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.TIFFDirectory;
import com.sun.media.jai.codec.TIFFEncodeParam;
import com.sun.media.jai.codec.TIFFField;
import com.sun.media.jai.codecimpl.TIFFImageDecoder;

public class Rotar
{
    // variables de objeto
    private RenderedOp image;
    private RenderedOp resultado;
    private FileSeekableStream is;
    private FileOutputStream os;
    private int code;

    // constantes
    private final static int TIFF_RESOLUTION_INCHES     = 2;

    /**
     * Constructor
     */
    public Rotar() {}

    /**
     * abrir imagen
     */
    public void abrir(String entrada) {
        try {
            is = new FileSeekableStream (entrada);
            image = JAI.create("stream", is);
            resultado = image;
        } catch (IOException e) {};
    }

    /**
     * ver compresion
     */
    public void verCompresion() {
        String[] formatos = ImageCodec.getDecoderNames(is);
        System.out.println("Numero de compresores posibles: "+formatos.length);
        for (int i=0; i<formatos.length; i++) {
            System.out.println("    Formato "+i+" : "+formatos[i]);
        }
        System.out.println("\n");
    }

    /**
     * ver datos de la imagen
     */
    public void verDatosTIFF() {
      try {
        TIFFDirectory td = new TIFFDirectory(is, 0);

        // ver resolucion de imagen
        float resX = td.getFieldAsFloat(TIFFImageDecoder.TIFF_X_RESOLUTION);
        float resY = td.getFieldAsFloat(TIFFImageDecoder.TIFF_Y_RESOLUTION);

        // ver tipo de compresion
        code = (int)td.getFieldAsLong(TIFFImageDecoder.TIFF_COMPRESSION);

        // ver altura y anchura de imagen
        int anchura = (int)td.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_WIDTH);
        int altura = (int)td.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH);

        // imprime por pantalla los parametros
        System.out.println("");
        System.out.println("Resolucion X: "+resX);
        System.out.println("Resolucion Y: "+resY);
        imprimirCompresion();
        System.out.println("      Altura: "+altura);
        System.out.println("     Anchura: "+anchura);
        System.out.println("");

      } catch (IOException e) {};
    }

    /**
     * imprimir tipo de compresion
     */
    public void imprimirCompresion() {
        System.out.print("  Compresion: ");
        switch (code) {
            case 1: System.out.println("None");
                    break;
            case 2: System.out.println("Grupo 3-1D");
                    break;
            case 3: System.out.println("Grupo 3-2D");
                    break;
            case 4: System.out.println("Grupo 4");
                    break;
            case 5: System.out.println("LZW");
                    break;
            case 7: System.out.println("JPG-TTN2");
                    break;
        case 32946: System.out.println("Deflate");
                    break;
           default: System.out.println("No registrada");
                    break;
        }
    }

    /**
     * rotar imagen 90 grados
     */
    public void rotarImagen(String entrada) {
        int anchura=image.getWidth();
        int altura=image.getHeight();
        if (anchura > altura) {
            System.out.println("Imagen "+entrada+" apaisada. Girando...");
            ParameterBlock params = new ParameterBlock();
            params.addSource(image);
            params.add((float)anchura/2);
            params.add((float)altura/2);
            params.add((float)Math.toRadians(270));
            params.add(Interpolation.getInstance(Interpolation.INTERP_BILINEAR));
            resultado = JAI.create("rotate", params);
        }
        else {
            System.out.println("Imagen "+entrada+" correcta.");
        }
    }

    /**
     * cambiar resolucion (ppp) del archivo TIFF
     */
    public TIFFField[] nuevaResolucion() {
        TIFFField[] tiffFields = new TIFFField[3];
        tiffFields[0] = new TIFFField(TIFFImageDecoder.TIFF_X_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, new long[][] {{200,1}});
        tiffFields[1] = new TIFFField(TIFFImageDecoder.TIFF_Y_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, new long[][] {{200,1}});
        tiffFields[2] = new TIFFField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT, TIFFField.TIFF_SHORT, 1, new char[] {TIFF_RESOLUTION_INCHES} );
        return tiffFields;
    }

    /**
     * guardar imagen en fichero original
     */
    public void guardarImagen(String salida) {
      try {
        TIFFEncodeParam tiffEncoder = new TIFFEncodeParam();
        tiffEncoder.setCompression(code);
        tiffEncoder.setExtraFields(nuevaResolucion());

        FileOutputStream os = new FileOutputStream("C:\\Users\\Public\\Pictures\\Sample Pictures\\temp.tif");
        ImageEncoder encoder = ImageCodec.createImageEncoder("TIFF", os, tiffEncoder);
        encoder.encode(resultado);
        os.close();

        abrir("temp.tif");
        guardar(salida);
      } catch (FileNotFoundException e) {
      } catch (IOException ee) {}
    }

    /**
     * guardar imagen en fichero aparte
     */
    public void guardar(String salida) {
      try {
        TIFFEncodeParam tiffEncoder = new TIFFEncodeParam();
        tiffEncoder.setCompression(code);
        tiffEncoder.setExtraFields(nuevaResolucion());

        FileOutputStream os = new FileOutputStream(salida);
        ImageEncoder encoder = ImageCodec.createImageEncoder("TIFF", os, tiffEncoder);
        encoder.encode(resultado);
        os.close();
      } catch (FileNotFoundException e) {
      } catch (IOException ee) {}
    }

    /***************************************************************
     * programa principal
     ***************************************************************/
    public static void main(String[] args)
    {
      Rotar rotar = new Rotar();

      if (args.length != 1) {
          System.out.println("Formato: Rotar <img_entrada>");
        //  System.exit(0);
      }

      rotar.abrir("C:\\Users\\Public\\Pictures\\Sample Pictures\\06020014126_2.tif");
      rotar.verDatosTIFF();
      rotar.rotarImagen("C:\\Users\\Public\\Pictures\\Sample Pictures\\06020014126_2.tif");
      rotar.guardarImagen("C:\\Users\\Public\\Pictures\\Sample Pictures\\06020014126_2.tif");

      System.exit(0);
    }
}
